perm filename SPECS.RLL[RDG,DBL] blob
sn#610077 filedate 1981-09-07 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00002 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 A list of those additional values which get passed to
C00014 ENDMK
C⊗;
A list of those additional values which get passed to
GetValue, PutValue and friends.
<<<GetField and PutField will soon have a similiar list>>>
The third arg to GetValue - "other" in most functions - is an unordered list
(actually an FSet) whose elements may be:
(FAST-CACHE s1 s2 ... sN) -- this causes the atom Fast-Cache to be passed
to CacheValue, on its "why" list, for each slot, si.
(-CACHE s1 s2 ... sN) -- tells the get-values NOT to cache the computed
value of any slot si.
(-COMPUTE s1 s2 ... sN) -- the get-values will not bother computing the
value of any slt si; if the value isn't stored, just forget it.
(IGNORE-CACHE s1 s2 ... sN) -- the get-values will NOT use the stored value
of any slot si -- but rather will compute those values as needed.
(SAFESLOT s1 s2 ... sN) -- each si really is a slot; so don't bother to
confirm this.
(SAFEUNIT u1 u2 ... uN) -- each ui is really a unit.
---
[Note I am trying to adopt the convention that binary conditions be indicated
by using some name, prefixed by + or -, depending on sense. In general only
one form (eg either +←←← or -←←←) will be necessary, as the other sense is
the overall default. For example, +CACHE is superfluous.]
---
In addition, any of these elements can be a single atom -- one of that
{FAST-CACHE -CACHE -COMPUTE IGNORE-CACHE SAFESLOT SAFEUNIT} list.
In the first 4 cases, this means the implied action will happen to every slot.
An atomic SAFE←←←← applies only to the current slot or unit.
(This might be wrong; but it did save CONS cells for the standard cases.)
I reserve the right to further elaborate this convention to suit my whims
at any later date. For example, one may eventually want to be more specific
in determining which slot's values to, eg, ignore -- as in
(GetValue 'Fred 'Friends '((IGNORE-CACHE AllExamples (AnyFrog AllIsas)))),
which means the cached values as U:AllExamples will be ignored for all
units U, but that V:AllIsas will be accepted EXCEPT WHEN V=AnyFrog.
I cuurently have no use for such a "feature" - do you?
Another direction may be to have forms which are evaluated during the call,
will appropriate bindings --
(GetValue 'Fred 'Friends '((IGNORE-CACHE =Fn fn#37))),
where this fn#37 will be applied to the unit and slot being considered at
each (recursive) call to GetValue; and its values would be used as the set
of slots whose cached values should be ignored. A slight variation of this
would be something like (... ((IGNORE-CACHE =Pred= pred#82))), where pred#82
would be a predicate whose nonNIL response meant the argument should be
"ignore-cached". Once again, this sledge hammer may not ever be really needed,
but it has been considered.
Future directions:
(I'm sure I will need more of these values; but am waiting for a forcing
example before implementing and documenting those options.)
(i) (USE-VALUE (u1 s1 val1) ... (uN sN vN)) meaning "pretend"
the value of ui:si is really vali -- don't bother to compute it.
(ii) There's also some hassles when dealing with those *DO* special
values -- should they be treated as simple "syntactic" values, or
"evaluated" -- ie how do I store the "value" (*DO* FSeeUnit SofU)
as U:S? As I said, more on this as this comes important -- unless
you've some insights on this whole can of worms.]
-------
Onto the putting functions.
There are basically two types of values. I'll resent the primitive ones first:
The final argument is a set of zero or more elements, each of the form
[These apply to any of PutValue, AddValue, DeleteValue, SubstValue]
-VERIFY -- there is no need to verify that this value is appropriate, or
that this slot belongs on this unit. (Yes, this may indeed be
confusing two distinct functions. Eventually I worry about this,
if I have to.)
-INVERSES -- do NOT now add on inverse links (this is useful when this
particular PutValue was itself adding backpointers. If not for this
facility that process would always lead to an infinite loop...)
-DEPENDENCIES -- do NOT do the other miscellaneous KB updates which result
from this modification.
[This only applies to PutValue]
+ALWAYS-UPDATE -- go thru the motion of adding inverse links, and other
after-put-value functions after performing an update -- even if the
value seems NOT to have changed. (Ie pretend the old value was really
RecomputeMe.) This is needed to handle the case of unit
initialization, when values are first simply UA-PUTVALUEd onto the
unit, and later have to be actually PutValue-d.
[These only apply to AddValue, DeleteValue, & SubstValue]
+COMPUTE-INITIAL -- What should you do when you've been told to add on a
new value, V, onto U:S when there is no value of U:S?
There seem two possibilities:
(1) do everything you can to compute the value of U:S,
and then add on V.
(2) simply go on, (leaving U:S uncomputed) with the assurance that
any one from now on who wants
to find the value of U:S will specifically ask for it, using
GetValue; which will now have to compute it.
The asssumption is that S:ToCompute will now catch this new V.
Anyway, it turns out that both of these cases come up -- hence this
extra parameter.
[Note I believe the current programs will always compute the value if
the slot is primitive -- as this means the value is NoEntry or
NoEntries, depending on the format of the slot. This is probably
the wrong approach...]
N-Values -- In general one wants to add on just one value, V, to a value of
U:S. However there are times one may want to add a slew of {Vi} at
once. The purpose of this value is to distinguish these cases.
Note this is well defined for both AddValue and DeleteValue; but
may lead to confusion for SubstValue, if we want to replace N values
with M values, when N <> M. Of course we may simply bar this operation
in general.
-------
Now for the other type of values. First, by way of motivation, ask
why PutValue should know anything about adding inverses? I'll
agree that DefaultPutValue should, but things at this level should be totally
invisible to the general user-level functions. It should be sufficient
to tell PutValue that we are now AddingInverses, and nothing more.
The functions which PutValue calls, such as DefaultPutValue, should
now infer that this means not to add inverse pointers to these, ...
This implies we should pass values like AddInverse in that extra argument.
However, there are times internal functions "know" what is needed -- and
why should the other functions force them to pass these indirect values?
Solution: Allow either type to be passed.
Of course we need a table which relates those parameters with what they really
mean --
Verify? Inverse? Dependencies?
New-Unit + +
KB-Consistency +
AddInverse +
DeleteInverse +
RemovingForeigners +
UnitRenamed +
UnitDeleted +
<default> + + +
[Legend: the absense of a "+" means -←←←←, for parameter ←←←? above.]
This conversion takes place in Default←←←Value,
for ←←← in {Put Add Delete Subst}. (Inferior functions will assume they
are getting the more primitive forms.)